package com.example.understandvideo.service;

import com.example.understandvideo.pojo.*;
import com.example.understandvideo.pojo.common.*;
import com.example.understandvideo.service.transcode.*;
import com.example.understandvideo.tool.*;
import com.google.gson.Gson;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.*;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.util.UriTemplate;

import javax.annotation.Resource;
import java.io.File;
import java.net.URI;
import java.time.LocalDate;
import java.util.*;

import static java.lang.Thread.sleep;

/**
 * 通用引擎调用服务
 */
@Slf4j
@Service
public class EngineService {
    @Resource
    private CommonService commonService;
    @Resource
    private TranscodeService transcodeService;


    /**
     * 获取镜头切换
     *
     * @return
     */
    public CameraCutResult getCameraCuts(String filepath) {
        /**
         * 基础步骤，对视频进行每秒抽帧，然后每两帧送给ai跑，看看是否有人物变动，若是则记录当前帧，
         */
        File file = new File(filepath);
        String name = commonService.getFileNameWithoutExtension(file.getName());
        String targetPicPath = commonService.getWorkSpace() + "thumbnail" + File.separator + LocalDate.now() + File.separator + name + File.separator;
        File targetPicDir = new File(targetPicPath);
        if (!targetPicDir.exists()) {
            targetPicDir.mkdirs();
        }
        List<DrawResultObject> picList = new ArrayList<>();
        //抽帧
        try {
            VideoFrameExtractor extractor = new VideoFrameExtractor(commonService.getFfmpegExcFileName());
            // 每秒抽取1帧
            int framesPerSecond = 1;
            // 调用方法抽取帧
            List<String> frames = extractor.extractFramesV4(filepath, targetPicPath, framesPerSecond);
            for (String frame : frames) {
                DrawResultObject object = new DrawResultObject();
                object.setSecond(commonService.extractAndConvert(frame));
                object.setPicture(frame);
                picList.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //结果排序
        picList.sort(Comparator.comparing(DrawResultObject::getSecond));
        //ai判断
        List<Long> cutPointList = new ArrayList<>();
        List<String> errorLogList = new ArrayList<>();
        for (int i = 0; i < picList.size() - 1; i++) {
            DrawResultObject targetDraw = picList.get(i);
            try {
                log.info("第 {} 秒", picList.get(i).getSecond());
                DrawResultObject nextDraw = picList.get(i + 1);
                List<String> picCodeList = new ArrayList<>();
                picCodeList.add(Tools.readImage(targetDraw.getPicture()));
                picCodeList.add(Tools.readImage(nextDraw.getPicture()));
                Boolean checkCutFlag = smartRequestForCameraCuts(commonService.getAIModelName(), picCodeList);
                if (checkCutFlag) {
                    cutPointList.add(targetDraw.getSecond());
                }
            } catch (Exception e) {
                errorLogList.add("第 " + targetDraw.getSecond() + " 秒的人物切换大模型识别错误");
                e.printStackTrace();
            }
        }
        //对原始数据做封装处理
        //将秒转化为毫秒
        List<CameraCutPoint> pointList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(cutPointList)) {
            cutPointList.sort(Comparator.comparing(Long::intValue));
            if (cutPointList.get(0) != 0) {
                CameraCutPoint firstPoint = new CameraCutPoint();
                firstPoint.setIndex(0);
                firstPoint.setStartTime(0L);
                firstPoint.setEndTime(cutPointList.get(0) * 1000);
                pointList.add(firstPoint);
            }
            for (int i = 0; i < cutPointList.size() - 1; i++) {
                CameraCutPoint point = new CameraCutPoint();
                point.setIndex(i + 1);
                point.setStartTime(cutPointList.get(i) * 1000);
                point.setEndTime(cutPointList.get(i + 1) * 1000);
                pointList.add(point);
            }
        }
        String logMessage = null;
        if (!CollectionUtils.isEmpty(errorLogList)) {
            logMessage = StringUtils.join(errorLogList, "\n");
        }
        //包装结果并返回
        CameraCutResult cameraCutResult = new CameraCutResult();
        cameraCutResult.setCutPointList(pointList);
        cameraCutResult.setErrorLog(logMessage);
        return cameraCutResult;
    }

    private Boolean smartRequestForCameraCuts(String model, List<String> picCodeList) {
        Gson gson = new Gson();
        //参数
        Request request = new Request();
        request.setModel(model);
        Message message = new Message();
        message.setRole("user");
        List<Content> content = new ArrayList<>();
        Content question = new Content();
        question.setType("text");
        question.setText("这是同一视频的两帧画面，请问这两帧画面中是否出现了人物切换的情况，若是返回yes及内容解析，若没有出现则返回no及内容解析");
        content.add(question);
        for (String picCode : picCodeList) {
            Content pic = new Content();
            pic.setType("image_url");
            pic.setImage_url(new ImageUrl(picCode));
            content.add(pic);
        }
        message.setContent(content);
        request.setMessages(Collections.singletonList(message));
        String gsonStr = gson.toJson(request);
        String result = HttpTool.post(gsonStr);
        String resultData = JsonUtils.extractContentFromStrJson(result);
        if (resultData.contains("yes")) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }


    public TranscodeVideoResult transcodeVideo(String filepath, CameraCutPoint point) throws InterruptedException {
        /**
         * 基础步骤，对视频进行每秒抽帧，然后每两帧送给ai跑，看看是否有人物变动，若是则记录当前帧，
         */
        File file = new File(filepath);
        String name = commonService.getFileNameWithoutExtension(file.getName());
        String targetDirPath = commonService.getWorkSpace() + "transcode" + File.separator + LocalDate.now() + File.separator + name + File.separator;
        //拆条数据
        TimeSlice timeSlice = new TimeSlice();
        timeSlice.setStart(DateFormatUtil.formatDateToHHmmssV2(point.getStartTime(), Boolean.TRUE));
        timeSlice.setEnd(DateFormatUtil.formatDateToHHmmssV2(point.getEndTime(), Boolean.TRUE));
        CutCloudTaskResponse response = transcodeService.sendCommonCloudTask(Collections.singletonList(timeSlice), file.getAbsolutePath(), targetDirPath, "智能理解任务");
        do {
            sleep(3000);
            String body = HttpTool.getXmlStr(commonService.getServerAddress() + "/api/task/" + response.getCloudId() + "/progress");
            CloudResults resultTask = (CloudResults) XMLUtil.convertXmlStrToObject(CloudResults.class, body);
            String status = resultTask.getResults().get(0).getStatus();
            if (StringUtils.isNotBlank(status) && status.contains("ERROR")) {
                TranscodeVideoResult result = new TranscodeVideoResult();
                result.setErrorLog("视频合并转码生成失败！");
                return result;
            } else if (StringUtils.isNotBlank(status) && status.contains("COMPLETED")) {
                TranscodeVideoResult result = new TranscodeVideoResult();
                result.setFilepath(response.getTargetPath());
                return result;
            }
        } while (true);
    }

    public ThumbnailResult getPPTThumbnail(String filepath){
        /**
         * 基础步骤，对视频进行每秒抽帧，然后每两帧送给ai跑，看看是否有人物变动，若是则记录当前帧，
         */
        File file = new File(filepath);
        String name = commonService.getFileNameWithoutExtension(file.getName());
        String targetPicPath = commonService.getWorkSpace() + "thumbnail" + File.separator + LocalDate.now() + File.separator + name + File.separator;
        File targetPicDir = new File(targetPicPath);
        if (!targetPicDir.exists()) {
            targetPicDir.mkdirs();
        }
        List<DrawResultObject> picList = new ArrayList<>();
        //抽帧
        try {
            VideoFrameExtractor extractor = new VideoFrameExtractor(commonService.getFfmpegExcFileName());
            // 每秒抽取1帧
            int framesPerSecond = 1;
            // 调用方法抽取帧
            List<String> frames = extractor.extractFramesV4(filepath, targetPicPath, framesPerSecond);
            for (String frame : frames) {
                DrawResultObject object = new DrawResultObject();
                object.setSecond(commonService.extractAndConvert(frame));
                object.setPicture(frame);
                picList.add(object);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //ai判断
        List<String> result = new ArrayList<>();
        List<String> errorLogList = new ArrayList<>();
        for(DrawResultObject drawResultObject : picList){
            try {
                log.info("第 {} 秒", drawResultObject.getSecond());
                Boolean checkCutFlag = smartRequestForPPTThumbnail(commonService.getAIModelName(), Tools.readImage(drawResultObject.getPicture()));
                if (checkCutFlag) {
                    result.add(drawResultObject.getPicture());
                }
            } catch (Exception e) {
                errorLogList.add("第 " + drawResultObject.getSecond() + " 秒的人物切换大模型识别错误");
                e.printStackTrace();
            }
        }
        //包装结果并返回
        Gson gson = new Gson();
        ThumbnailResult thumbnailResult = new ThumbnailResult();
        thumbnailResult.setResult(gson.toJson(result));
        thumbnailResult.setErrorLog(gson.toJson(errorLogList));
        return thumbnailResult;
    }

    private Boolean smartRequestForPPTThumbnail(String model, String picCode) {
        Gson gson = new Gson();
        //参数
        Request request = new Request();
        request.setModel(model);
        Message message = new Message();
        message.setRole("user");
        List<Content> content = new ArrayList<>();
        Content question = new Content();
        question.setType("text");
        question.setText("这是一张图片，请告诉我，这张图片中存在ppt素材吗,若存在返回yes和图片解析，若没有出现则返回no和图片解析");
        content.add(question);
        Content pic = new Content();
        pic.setType("image_url");
        pic.setImage_url(new ImageUrl(picCode));
        content.add(pic);
        message.setContent(content);
        request.setMessages(Collections.singletonList(message));
        String gsonStr = gson.toJson(request);
        String result = HttpTool.post(gsonStr);
        String resultData = JsonUtils.extractContentFromStrJson(result);
        if (resultData.contains("yes")) {
            return Boolean.TRUE;
        } else {
            return Boolean.FALSE;
        }
    }


}
